﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Globalization;

namespace BDSim
{
    /// <summary>
    /// WalkerSatConstWnd.xaml 的交互逻辑
    /// </summary>
    public partial class WalkerSatConstWnd : Window
    {
        public WalkerSatConstWnd()
        {
            InitializeComponent();
        }

        #region 成员

        //星座预览中卫星轨道的颜色字典
        Dictionary<int, Color> DicColor = new Dictionary<int, Color>() 
        {
            {0,Colors.Green},
            {1,Colors.Red},
            {2,Colors.Orange},
            {3,Colors.Aqua},
            {4,Colors.Yellow},
            {5,Colors.BurlyWood},
            {6,Colors.Coral},
            {7,Colors.Cyan}
        };

        //Walker星座的卫星坐标数据
        public NodePosVel[] Satoutput;

        //Walker星座的卫星轨道数据
        public NodePosVel[] Trackoutput;

        //种子卫星的坐标
        public NodePosVel OrbitP = new NodePosVel() { x = 16983361.425618779, y = -20353706.440648332, z = 3.0326473751327021E-07, vx = 1709.4500488214646, vy = 1426.384334613964, vz = 3179.6078039000004 };

        //所有MEO卫星位置与速度数据
        public List<NodePosVelClass> MEOPV = new List<NodePosVelClass>();


        //MEO卫星的轨道个数
        public int MeoOrbitNum;

        #endregion



        #region 方法


        #region 轨道历元和坐标单位选择变化事件响应函数

        /// <summary>
        /// MEO的ECI坐标设置界面卫星单位选择变化事件响应函数
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MEOECIComboSelectChanged(object sender, SelectionChangedEventArgs e)
        {
            switch (((ComboBox)sender).Name)
            {
                case "MEOECI_ComX":
                    switch ((string)e.AddedItems[0])
                    {
                        case "m":
                            ((WalkerSatConstWndViewModel)DataContext).MEOECIOrbit.X *= 1000;
                            break;
                        case "km":
                            ((WalkerSatConstWndViewModel)DataContext).MEOECIOrbit.X /= 1000;
                            break;
                        default:
                            break;
                    }
                    break;

                case "MEOECI_ComY":
                    switch ((string)e.AddedItems[0])
                    {
                        case "m":
                            ((WalkerSatConstWndViewModel)DataContext).MEOECIOrbit.Y *= 1000;
                            break;
                        case "km":
                            ((WalkerSatConstWndViewModel)DataContext).MEOECIOrbit.Y /= 1000;
                            break;
                        default:
                            break;
                    }
                    break;
                case "MEOECI_ComZ":
                    switch ((string)e.AddedItems[0])
                    {
                        case "m":
                            ((WalkerSatConstWndViewModel)DataContext).MEOECIOrbit.Z *= 1000;
                            break;
                        case "km":
                            ((WalkerSatConstWndViewModel)DataContext).MEOECIOrbit.Z /= 1000;
                            break;
                        default:
                            break;
                    }
                    break;
                case "MEOECI_ComVX":
                    switch ((string)e.AddedItems[0])
                    {
                        case "m/s":
                            ((WalkerSatConstWndViewModel)DataContext).MEOECIOrbit.VX *= 1000;
                            break;
                        case "km/s":
                            ((WalkerSatConstWndViewModel)DataContext).MEOECIOrbit.VX /= 1000;
                            break;
                        default:
                            break;
                    }
                    break;
                case "MEOECI_ComVY":
                    switch ((string)e.AddedItems[0])
                    {
                        case "m/s":
                            ((WalkerSatConstWndViewModel)DataContext).MEOECIOrbit.VY *= 1000;
                            break;
                        case "km/s":
                            ((WalkerSatConstWndViewModel)DataContext).MEOECIOrbit.VY /= 1000;
                            break;
                        default:
                            break;
                    }
                    break;
                case "MEOECI_ComVZ":
                    switch ((string)e.AddedItems[0])
                    {
                        case "m/s":
                            ((WalkerSatConstWndViewModel)DataContext).MEOECIOrbit.VZ *= 1000;
                            break;
                        case "km/s":
                            ((WalkerSatConstWndViewModel)DataContext).MEOECIOrbit.VZ /= 1000;
                            break;
                        default:
                            break;
                    }
                    break;
                default:
                    break;
            }

        }

        /// <summary>
        /// MEO的ECF坐标设置界面卫星单位选择变化事件响应函数
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MEOECFComboSelectChanged(object sender, SelectionChangedEventArgs e)
        {
            switch (((ComboBox)sender).Name)
            {
                case "MEOECF_ComX":
                    switch ((string)e.AddedItems[0])
                    {
                        case "m":
                            ((WalkerSatConstWndViewModel)DataContext).MEOECFOrbit.X *= 1000;
                            break;
                        case "km":
                            ((WalkerSatConstWndViewModel)DataContext).MEOECFOrbit.X /= 1000;
                            break;
                        default:
                            break;
                    }
                    break;

                case "MEOECF_ComY":
                    switch ((string)e.AddedItems[0])
                    {
                        case "m":
                            ((WalkerSatConstWndViewModel)DataContext).MEOECFOrbit.Y *= 1000;
                            break;
                        case "km":
                            ((WalkerSatConstWndViewModel)DataContext).MEOECFOrbit.Y /= 1000;
                            break;
                        default:
                            break;
                    }
                    break;
                case "MEOECF_ComZ":
                    switch ((string)e.AddedItems[0])
                    {
                        case "m":
                            ((WalkerSatConstWndViewModel)DataContext).MEOECFOrbit.Z *= 1000;
                            break;
                        case "km":
                            ((WalkerSatConstWndViewModel)DataContext).MEOECFOrbit.Z /= 1000;
                            break;
                        default:
                            break;
                    }
                    break;
                case "MEOECF_ComVX":
                    switch ((string)e.AddedItems[0])
                    {
                        case "m/s":
                            ((WalkerSatConstWndViewModel)DataContext).MEOECFOrbit.VX *= 1000;
                            break;
                        case "km/s":
                            ((WalkerSatConstWndViewModel)DataContext).MEOECFOrbit.VX /= 1000;
                            break;
                        default:
                            break;
                    }
                    break;
                case "MEOECF_ComVY":
                    switch ((string)e.AddedItems[0])
                    {
                        case "m/s":
                            ((WalkerSatConstWndViewModel)DataContext).MEOECFOrbit.VY *= 1000;
                            break;
                        case "km/s":
                            ((WalkerSatConstWndViewModel)DataContext).MEOECFOrbit.VY /= 1000;
                            break;
                        default:
                            break;
                    }
                    break;
                case "MEOECF_ComVZ":
                    switch ((string)e.AddedItems[0])
                    {
                        case "m/s":
                            ((WalkerSatConstWndViewModel)DataContext).MEOECFOrbit.VZ *= 1000;
                            break;
                        case "km/s":
                            ((WalkerSatConstWndViewModel)DataContext).MEOECFOrbit.VZ /= 1000;
                            break;
                        default:
                            break;
                    }
                    break;
                default:
                    break;
            }
        }

        /// <summary>
        /// MEO的六根数设置界面卫星单位选择变化事件响应函数
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MEOElemComboSelectChanged(object sender, SelectionChangedEventArgs e)
        {
            double Rad = 180.0 / Math.PI;//1 (rad)=180/PI (deg)
            switch (((ComboBox)sender).Name)
            {
                case "MEOElem_ComA":
                    switch ((string)e.AddedItems[0])
                    {
                        case "m":
                            ((WalkerSatConstWndViewModel)DataContext).MEOElemOrbit.A *= 1000;
                            break;
                        case "km":
                            ((WalkerSatConstWndViewModel)DataContext).MEOElemOrbit.A /= 1000;
                            break;
                        default:
                            break;
                    }
                    break;

                case "MEOElem_ComI":
                    switch ((string)e.AddedItems[0])
                    {
                        case "deg":
                            ((WalkerSatConstWndViewModel)DataContext).MEOElemOrbit.I *= Rad;
                            break;
                        case "rad":
                            ((WalkerSatConstWndViewModel)DataContext).MEOElemOrbit.I /= Rad;
                            break;
                        default:
                            break;
                    }
                    break;
                case "MEOElem_ComO":
                    switch ((string)e.AddedItems[0])
                    {
                        case "deg":
                            ((WalkerSatConstWndViewModel)DataContext).MEOElemOrbit.O *= Rad;
                            break;
                        case "rad":
                            ((WalkerSatConstWndViewModel)DataContext).MEOElemOrbit.O /= Rad;
                            break;
                        default:
                            break;
                    }
                    break;
                case "MEOElem_ComOKind":
                    switch ((string)e.AddedItems[0])
                    {
                        case "RAAN/ECI"://Lon->RAAN
                            {
                                double O2 = ((WalkerSatConstWndViewModel)DataContext).RAAN2Lon("MEO", 2);
                                if (((WalkerSatConstWndViewModel)DataContext).WalkerOrbitEleUnitSelect.OmegaUnit == "deg")
                                {
                                    ((WalkerSatConstWndViewModel)DataContext).MEOElemOrbit.O = O2;
                                }
                                else
                                {
                                    ((WalkerSatConstWndViewModel)DataContext).MEOElemOrbit.O = O2 * Math.PI / 180.0;
                                }

                            }
                            break;
                        case "Lon/ECF"://RAAN->Lon
                            double O1 = ((WalkerSatConstWndViewModel)DataContext).RAAN2Lon("MEO", 1);
                            if (((WalkerSatConstWndViewModel)DataContext).WalkerOrbitEleUnitSelect.OmegaUnit == "deg")
                            {
                                ((WalkerSatConstWndViewModel)DataContext).MEOElemOrbit.O = O1;
                            }
                            else
                            {
                                ((WalkerSatConstWndViewModel)DataContext).MEOElemOrbit.O = O1 * Math.PI / 180.0;
                            }
                            break;
                        default:
                            break;
                    }
                    break;
                case "MEOElem_ComW":
                    switch ((string)e.AddedItems[0])
                    {
                        case "deg":
                            ((WalkerSatConstWndViewModel)DataContext).MEOElemOrbit.W *= Rad;
                            break;
                        case "rad":
                            ((WalkerSatConstWndViewModel)DataContext).MEOElemOrbit.W /= Rad;
                            break;
                        default:
                            break;
                    }
                    break;
                case "MEOElem_ComF":
                    switch ((string)e.AddedItems[0])
                    {
                        case "deg":
                            ((WalkerSatConstWndViewModel)DataContext).MEOElemOrbit.F *= Rad;
                            break;
                        case "rad":
                            ((WalkerSatConstWndViewModel)DataContext).MEOElemOrbit.F /= Rad;
                            break;
                        default:
                            break;
                    }
                    break;
                default:
                    break;
            }

        }

        /// <summary>
        /// MEO的历元设置界面卫星单位选择变化事件响应函数
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MEOTimeComSelectChanged(object sender, SelectionChangedEventArgs e)
        {
            UTCTime epoh = new UTCTime();
            if (e.RemovedItems.Count != 0)
            {
                switch ((string)e.RemovedItems[0])//原来的选择
                {
                    case "UTC":
                        string[] time = ((WalkerSatConstWndViewModel)DataContext).MEOInitTime.Split(':', '-', ' ');
                        if (time.Length == 6)
                        {
                            epoh.Year = Convert.ToInt32(time[0]);
                            epoh.mon = Convert.ToInt32(time[1]);
                            epoh.day = Convert.ToInt32(time[2]);
                            epoh.Hour = Convert.ToInt32(time[3]);
                            epoh.Min = Convert.ToInt32(time[4]);
                            epoh.sec = Convert.ToDouble(time[5]);
                            TimeSpaceDll.CAL2UTC(out epoh, 1);//UTC转JD
                        }
                        switch ((string)e.AddedItems[0])//现在选择的
                        {
                            case "JD":
                                ((WalkerSatConstWndViewModel)DataContext).MEOInitTime = epoh.JD.ToString();
                                break;
                            case "MJD":
                                ((WalkerSatConstWndViewModel)DataContext).MEOInitTime = (epoh.JD - 2400000.5).ToString();
                                break;
                        }
                        break;
                    case "JD"://以前的选择
                        epoh.JD = Convert.ToDouble(((WalkerSatConstWndViewModel)DataContext).MEOInitTime);
                        TimeSpaceDll.CAL2UTC(out epoh, 2);//JD转UTC
                        switch ((string)e.AddedItems[0])//现在选择的
                        {
                            case "UTC":
                                ((WalkerSatConstWndViewModel)DataContext).MEOInitTime = epoh.ToString();
                                break;
                            case "MJD":
                                ((WalkerSatConstWndViewModel)DataContext).MEOInitTime = (epoh.JD - 2400000.5).ToString();
                                break;
                        }
                        break;
                    case "MJD":
                        epoh.JD = Convert.ToDouble(((WalkerSatConstWndViewModel)DataContext).MEOInitTime) + 2400000.5;
                        TimeSpaceDll.CAL2UTC(out epoh, 2);//JD转UTC
                        switch ((string)e.AddedItems[0])//现在选择的
                        {
                            case "UTC":
                                ((WalkerSatConstWndViewModel)DataContext).MEOInitTime = epoh.ToString();
                                break;
                            case "JD":
                                ((WalkerSatConstWndViewModel)DataContext).MEOInitTime = epoh.JD.ToString();
                                break;
                        }
                        break;
                    default:
                        break;
                }
            }
        }
        

        #endregion

        #region 私有方法

        //卫星轨道预览中鼠标中滚轮响应函数
        private void Window_MouseWheel(object sender, MouseWheelEventArgs e)
        {
           // SatPreView1.OnMouseWheel(sender, e);
        }

        /// <summary>
        /// 获取用户输入的卫星个数的X，Y，Z坐标参数       
        /// </summary>
        /// <returns></returns>
        List<double> GetSatPositon(NodePosVel[] output)
        {
            List<double> PosList = new List<double>();
            int i = 0;
            foreach (var item in output)
            {
                if (item.x != 0 && item.y != 0 && item.z != 0 & item.vx != 0 && item.vy != 0 && item.vz != 0)
                {
                    PosList.Add(100 + (item.x / 400000.0));
                    PosList.Add(100 + (item.y / 400000.0));
                    PosList.Add(100 + (item.z / 400000.0));
                }
                i += 3;
            }
            return PosList;

        }

        /// <summary>
        /// 此处使用经度解算升交点赤经（注：用UTC代替了UT1，使用格林尼治平恒星时代替了真恒星时，需要再修改）
        /// </summary>
        /// <param name="TrueAnomaly">单位为弧度</param>
        /// <param name="Lon">单位为弧度</param>
        /// <param name="a">单位为m</param>
        /// <param name="UT1">JD</param>
        /// <returns>度</returns>
        public static double Lon2RAAN(double TrueAnomaly, double Lon, double a, double UT1)
        {
            //TrueAnomaly = TrueAnomaly * Math.PI / 180;//度转弧度
            //Lon = Lon * Math.PI / 180;//度转弧度

            double GM = 3.986004418E14;
            //double We = 7.299115e-5;
            double dt = TrueAnomaly * Math.Sqrt(Math.Pow(a, 3) / GM);
            double du = UT1 - 2451545 - dt / 86400.0;
            double Tu = du / 36525;
            double Tu2 = Tu * Tu;
            double Tu3 = Tu * Tu2;
            double GMST = TimeAng(0, 0, 67310.54841) + TimeAng(876600, 0, 8640184.812866) * Tu +
                    TimeAng(0, 0, 0.093104) * Tu2 - TimeAng(0, 0, 6.2E-6) * Tu3;

            double RAAN = Lon + GMST;
            RAAN = RAAN % (2 * Math.PI);
            RAAN = RAAN * 180 / Math.PI;//弧度转度
            return RAAN;
        }

        /// <summary>
        /// 此处使用升交点赤经解算经度（注：用UTC代替了UT1，使用格林尼治平恒星时代替了真恒星时，需要再修改）
        /// </summary>
        /// <param name="TrueAnomaly">真近点角，单位为弧度</param>
        /// <param name="raan">升交点赤经，单位为弧度</param>
        /// <param name="a">半长轴，单位为m</param>
        /// <param name="UT1">儒略日，JD</param>
        /// <returns>度</returns>
        public static double RAAN2Lon(double TrueAnomaly, double raan, double a, double UT1)
        {
            //TrueAnomaly = TrueAnomaly * Math.PI / 180;//度转弧度
            //raan = raan * Math.PI / 180;//度转弧度

            double GM = 3.986004418E14;
            //double We = 7.299115e-5;
            double dt = TrueAnomaly * Math.Sqrt(Math.Pow(a, 3) / GM);
            double du = UT1 - 2451545 - dt / 86400.0;
            double Tu = du / 36525;
            double Tu2 = Tu * Tu;
            double Tu3 = Tu * Tu2;
            double GMST = TimeAng(0, 0, 67310.54841) + TimeAng(876600, 0, 8640184.812866) * Tu +
                    TimeAng(0, 0, 0.093104) * Tu2 - TimeAng(0, 0, 6.2E-6) * Tu3;
            double lon = raan - GMST;
            lon = lon % (2 * Math.PI);
            lon = lon * 180 / Math.PI;//弧度转度
            return lon;
        }

        public static double TimeAng(double h, double m, double s)
        {
            double result;
            result = (((h) + (m) / 60.0 + (s) / 3600.0) * 15.0 * Math.PI / 180);
            return result;
        }

        /// <summary>
        /// 屏蔽非法按键   
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void TextBox_KeyDown(object sender, KeyEventArgs e)
        {
            //屏蔽非法按键
            if ((e.Key >= Key.NumPad0 && e.Key <= Key.NumPad9))
            {
                e.Handled = false;
                return;
            }
            else if (e.Key >= Key.D0 && e.Key <= Key.D9)
            {
                e.Handled = false;
                return;
            }
            else if (e.Key == Key.Decimal || e.Key == Key.OemPeriod)
            {
                e.Handled = false;
                return;
            }
            e.Handled = true;
        }

        /// <summary>
        /// 确认当前设置，退出卫星参数配置界面    
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void EnSure_Click(object sender, RoutedEventArgs e)
        {
            this.DialogResult = true;
        }

        /// <summary>
        /// MEO卫星星座参数取消应用    
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Cancel_Click(object sender, RoutedEventArgs e)
        {
            this.DialogResult = false;
        }

   


        /// <summary>
        /// 窗口加载响应函数
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            //初始化时间和坐标
            //OrbitP.epoch.JD = 2457297;
            //BaseFunDLL.CAL2UTC(out OrbitP.epoch , 2);
            ((WalkerSatConstWndViewModel)DataContext).InitOrbit(OrbitP);
        }

        #endregion

        #endregion

    }



}

